﻿using System.Collections.Generic; 
using System.Text;
using JetBrains.Annotations;
using UnityEngine;
using XFFSM; 

/// <summary>
/// RuntimeFSMController 运行时的示例
/// </summary>
public class RuntimeFSMControllerInstance 
{

    public RuntimeFSMController RuntimeFSMController;

    // 所有的参数
    internal Dictionary<string, FSMParameterData> parameters = new Dictionary<string, FSMParameterData>();

    // 所有的状态
    internal Dictionary<string, FSMStateNode> states = new Dictionary<string, FSMStateNode>();

    internal List<FSMTransition> transitions = new List<FSMTransition>();

    // 默认状态
    internal FSMStateNode defaultState { get; private set; } = null;

    // 当前正在执行的状态
    public FSMStateNode currentState { get; private set; } = null;

    // 当前的过渡
    public FSMTransition currentTransition { get; private set; } = null;
    
    public FSMController FSMController { get; private set; }

    /// <summary>
    /// 状态切换计数(为了避免状态切换进入死循环)
    /// </summary>
    private Dictionary<string, int> state_count = new Dictionary<string, int>();

    /// <summary>
    /// 当前的帧数
    /// </summary>
    private int currentFrameCount = -1;

    /// <summary>
    /// 记录Trigger触发的次数
    /// </summary>
    private Dictionary<string, int> trigger_count = new Dictionary<string, int>(); 
    
    private List<string> trigerNames = new List<string>();

    public RuntimeFSMControllerInstance(RuntimeFSMController runtimeFSMController,FSMController controller) 
    {
        FSMController = controller;
        // 把数据复制一份
        if (runtimeFSMController == null) return;
        // 默认不执行任何状态
        currentState = null;
        RuntimeFSMController = GameObject.Instantiate(runtimeFSMController);
        // 参数
        parameters.Clear();
        for (int i = 0; i < RuntimeFSMController.parameters.Count; i++)
        {
            if (parameters.ContainsKey(RuntimeFSMController.parameters[i].name))
                continue;
            
            RuntimeFSMController.parameters[i].onValueChange = null;
            parameters.Add(RuntimeFSMController.parameters[i].name, RuntimeFSMController.parameters[i]);
        }

        // 状态
        states.Clear();
        for (int i = 0; i < RuntimeFSMController.states.Count; i++)
        {
            FSMStateNodeData stateData = RuntimeFSMController.states[i];
            FSMStateNode state = new FSMStateNode(stateData, this);

            if (states.ContainsKey(stateData.name)) continue;

            if (stateData.defaultState)
            {
                defaultState = state;
            }

            states.Add(stateData.name, state);
        }
        // 过渡
        transitions.Clear();
        foreach (var item in runtimeFSMController.transitions)
        {
            FSMTransition transition = new FSMTransition(this, item);
            transitions.Add(transition);
        } 
    }
    

    // 启动
    public void StartUp() 
    { 
        // 找到默认状态 切换
        SwitchState(defaultState, null);
    }

    public void Close() 
    {
        // 切换到空状态
        SwitchState(null, null);
    }
    internal void SwitchState(FSMStateNode state, FSMTransition transition)
    {
        if (Time.frameCount != currentFrameCount)
        { 
            currentFrameCount = Time.frameCount;
            state_count.Clear(); // 清空状态
        }
        // 添加状态
        AddStateCount(state.data.name);

        if (currentState != null)
        { 
            currentState.nextState = state.data.name;
            state.lastState = currentState.data.name;
            state.nextState = string.Empty;  // 把下一个状态的值设置为空
            currentState.OnExit();
        }

        currentState = state;
         
        state?.OnEnter();

        currentTransition = transition;
         
        if (currentState != null  )
        { 
            // 检测当前的状态是否有已经满足条件的过渡
            foreach (var item in transitions)
            {
                // 检测条件是否满足
                if (item.CheckConditionAndSwitch()) break;
            }
        }

    }

    public void SetBool(string name, bool v)
    {
        SetParamter(name, v ? 1 : 0, ParameterType.Bool);
    }

    public void SetFloat(string name, float v)
    {
        SetParamter(name, v, ParameterType.Float);
    }

    public void SetInt(string name, int v)
    {
        SetParamter(name, v, ParameterType.Int);
    }

    public void SetTrigger(string name)
    {
        FSMParameterData parameter;
        if (parameters.TryGetValue(name, out parameter))
        {
            if (parameter.parameterType == ParameterType.Trigger) 
            {
                if (trigger_count.ContainsKey(name)) 
                    trigger_count[name]++;
                else
                    trigger_count.Add(name, 1);
            }
        }
    }


    /// <summary>
    /// 当Trigger触发后还原trigger
    /// </summary>
    /// <param name="name"></param>
    internal void ClearTrigger(string name) 
    { 
        SetParamter(name, 0, ParameterType.Trigger);
    }

    public void ResetTrigger(string name)
    { 
        if(trigger_count.ContainsKey(name))
            trigger_count[name] = 0; 
        ClearTrigger(name);
    }

    private void SetParamter(string name, float v, ParameterType type)
    {
        FSMParameterData parameter;
        if (parameters.TryGetValue(name, out parameter))
        {
            if (parameter.parameterType == type)
                parameter.Value = v;
        }
    }

    private float GetParamter(string name) {
        FSMParameterData parameter;
        if (parameters.TryGetValue(name, out parameter))
            return parameter.value;
        return 0;
    }


    public void Update()
    {
        if (currentState != null) currentState.OnUpdate();
        // 更新Trigger
        UpdateTrigger();  
    }

    public void LateUpdate()
    {
        if (currentState != null) currentState.OnLateUpdate();
    }

    public void FixedUpdate()
    {
        if (currentState != null) currentState.OnFixedUpdate();
    }
     
    /// <summary>
    /// 添加计数
    /// </summary>
    /// <param name="stateName"></param>
    private void AddStateCount(string stateName)
    {
        if (state_count.ContainsKey(stateName))
            state_count[stateName]++;
        else
            state_count.Add(stateName, 0);

        if (state_count[stateName] > 20)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append("游戏物体:").Append(FSMController.gameObject.name)
                .Append("状态机:").Append(this.RuntimeFSMController.name).Append("检测到状态:");
            foreach (var item in state_count.Keys)
            {
                if (state_count[item] >= 19)
                {
                    stringBuilder.Append(item).Append(",");
                }
            }
            stringBuilder.Remove(stringBuilder.Length - 1, 1);
            stringBuilder.Append("之间频繁切换,请检查状态之间的过渡是否同时满足?过渡同时满足会导致死循环!");
            throw new System.Exception(stringBuilder.ToString());
        }
    }


    private void UpdateTrigger() 
    {
        trigerNames.Clear();
        // 更新Trigger
        foreach (var item in trigger_count.Keys)
        {
            if (trigger_count[item] > 0 && GetParamter(item) == 0)
            {
                SetParamter(item, 1, ParameterType.Trigger);
                trigerNames.Add(item);
            }
        }

        foreach (var item in trigerNames)
        {
            trigger_count[item]--;
        }
    }

}
